﻿using System;
using System.Reflection;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;
using System.Collections.Specialized;

namespace V5_Common
{
    /// <summary>
    /// SqlInPost 的摘要说明
    /// </summary>
    public class SqlhttpHandlers : IHttpHandlerFactory
    {
        public SqlhttpHandlers()
        {
        }

        public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
        {
            //得到编译实例(通过反射)
            PageHandlerFactory factory = (PageHandlerFactory)Activator.CreateInstance(typeof(PageHandlerFactory), true);
            IHttpHandler handler = factory.GetHandler(context, requestType, url, pathTranslated);
            //过滤字符串
            if (requestType == "POST")
            {
                Page page = handler as Page;
                if (page != null)
                    page.PreLoad += new EventHandler(FormFilterStrFactoryHandler_PreLoad);
            }
            if (requestType == "GET")
            {
                Page page = handler as Page;
                if (page != null)
                    page.PreLoad += new EventHandler(RequestFilterStrFactoryRHandler_PreLoad);
            }
            //返回
            return handler;
        }



        public virtual void ReleaseHandler(IHttpHandler handler)
        {

        }
        /// <summary>
        /// 过滤TextBox、Input和Textarea中非法字符
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FormFilterStrFactoryHandler_PreLoad(object sender, EventArgs e)
        {
            try
            {
                bool isSafe = true;
                Page page = sender as Page;
                NameValueCollection postData = page.Request.Form;
                foreach (string postKey in postData)
                {
                    Control ctl = page.FindControl(postKey);
                    if (ctl as TextBox != null)
                    {
                        ((TextBox)ctl).Text = ((TextBox)ctl).Text.Replace("'", "’");
                        string strValue = ((TextBox)ctl).Text.Trim();
                        if (!IsSafeString(strValue))
                        {
                            isSafe = false;
                            break;
                        }
                    }

                    else if (ctl as HtmlInputControl != null)
                    {
                        ((HtmlInputControl)ctl).Value = ((HtmlInputControl)ctl).Value.Replace("'", "’");
                        string strValue = ((HtmlInputControl)ctl).Value.Trim();
                        if (!IsSafeString(strValue))
                        {
                            isSafe = false;
                            break;
                        }
                    }

                    else if (ctl as HtmlTextArea != null)
                    {
                        ((HtmlTextArea)ctl).Value = ((HtmlTextArea)ctl).Value.Replace("'", "’");
                        string strValue = ((HtmlTextArea)ctl).Value.Trim();
                        if (!IsSafeString(strValue))
                        {
                            isSafe = false;
                            break;
                        }
                    }
                    else
                    {
                        var value = page.Request.Form[postKey];
                        WriteRequest(page, postKey, Utils.SafeString(value).Replace("'", "’"));
                    }
                }
                if (!isSafe)
                {
                    page.Response.Write("<b><font color='red' font-size=12pt>字符串格式非法!</font></b>");
                    page.Response.End();
                }
            }
            catch (Exception ex)
            {
                string a = ex.Message;
            }
        }


        private void WriteRequest(Page page, string key ,string value)
        {
            var oQuery = page.Request.QueryString;
            oQuery = (NameValueCollection)page.Request.GetType().GetField("_queryString", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(page.Request);
            PropertyInfo oReadable = oQuery.GetType().GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
            oReadable.SetValue(oQuery, false, null);
            oQuery[key] = value;
            oReadable.SetValue(oQuery, true, null);
        }

        /// <summary>
        /// 过滤QueryString 中的非法字符串
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void RequestFilterStrFactoryRHandler_PreLoad(object sender, EventArgs e)
        {
            try
            {
                Page page = sender as Page;
                NameValueCollection QueryNV = page.Request.QueryString;
                bool isSafe = true;
                for (int i = 0; i < QueryNV.Count; i++)
                {
                    if (!IsSafeString(QueryNV.Get(i)))
                    {
                        isSafe = false;
                        break;
                    }
                }
                if (!isSafe)
                {
                    page.Response.Write("<b><font color='red' font-size=12pt>字符串格式非法!</font></b>");
                    page.Response.End();
                }
            }
            catch { }
        }





        //判断是否为安全字符串
        public bool IsSafeString(string strText)
        {
            bool bResult = true;
            strText = Regex.Replace(strText, "[\\s]{1,}", "");    //two or more spaces
            strText = Regex.Replace(strText, "(<[b|B][r|R]/*>)+|(<[p|P](.|\\n)*?>)", "\n");    //<br>

            string[] UnSafeArray = new string[23];
            UnSafeArray[0] = "'";
            UnSafeArray[1] = "xp_cmdshell";
            UnSafeArray[2] = "declare";
            UnSafeArray[3] = "netlocalgroupadministrators";
            UnSafeArray[4] = "delete";
            UnSafeArray[5] = "truncate";
            UnSafeArray[6] = "netuser";
            UnSafeArray[7] = "/add";
            UnSafeArray[8] = "drop";
            UnSafeArray[9] = "update";
            UnSafeArray[10] = "select";
            UnSafeArray[11] = "union";
            UnSafeArray[12] = "exec";
            UnSafeArray[13] = "create";
            UnSafeArray[14] = "insertinto";
            UnSafeArray[15] = "sp_";
            UnSafeArray[16] = "exec";
            UnSafeArray[17] = "create";
            UnSafeArray[18] = "insertinto";
            UnSafeArray[19] = "masterdbo";
            UnSafeArray[20] = "sp_";
            UnSafeArray[21] = ";--";
            UnSafeArray[22] = "1=";
            foreach (string strValue in UnSafeArray)
            {

                if (strText.ToLower().IndexOf(strValue) > -1)
                {
                    bResult = false;
                    break;
                }
            }
            return bResult;
        }

    }
}